/**
 * @author Ahammer
 * @date   2010 04
 * @update 2010 06 case separate: only data where r2 > 0,9... collected and averaged
 * @update 2011 02 added regression data to table 
 * @update 2011 02 removing ModelListener extremely speeds up model configuration (adding columns, writing data,...) 
 */

/*
 * This file is part of Iqm.
 * Copyright (c) 2010-2011 Helmut Ahammer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package op;

import java.awt.image.Raster;
import java.util.Vector;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import tools.Higuchi;
import main.Board;
import main.IqmTools;
import main.Manager;

/**
 * This is the main image processing class
 * There exist two approaches:
 * A user defined JAI operator is just called 
 * or:
 * The actual processing is implemented in this class 
 */
public class IqmFracHiguchiOperator{ 


  public IqmFracHiguchiOperator() {
	  //WARNING: Don't declare fields here
	  //Fields declared here aren't thread safe!   
  }
  /**
   *  
   */
  private Vector<Double> removeZeroes (Vector<Double> data){
	  int length = data.size();
	  Vector<Double> dataNew = new Vector<Double>();
	  //dataNew = (Vector<Double>) data.clone();  //Essentiell!!!!!
	  for (int i = 0; i<length; i++){
		  double value = (Double)data.get(i);
		  if (value != 0) {
			  dataNew.add(value);			 
		  }
	  }	  
	  return dataNew;
  }
  
   
  /**
   * 
   * @param ParametrBlockJAI pb
   */
  public Object run(ParameterBlockJAI pbJAI){
	  	Object ob = null;
	  //Object ob = JAI.create("IqmFracHiguchi".toLowerCase(), pb, null); //geht nicht
	  //daher hier direkt implementiert
	  	PlanarImage pi = (PlanarImage) pbJAI.getSource(0);
	  	int numK      = pbJAI.getIntParameter("NumK");
	  	int optAppend = pbJAI.getIntParameter("Append");
	  	int optBack   = pbJAI.getIntParameter("Back");
	  	int optDx     = pbJAI.getIntParameter("Dx");	  	
	  	int optDy     = pbJAI.getIntParameter("Dy");	  	
	  	int regStart  = pbJAI.getIntParameter("RegStart");
	  	int regEnd    = pbJAI.getIntParameter("RegEnd");
	  	boolean optShowPlot = false;
	  	boolean optDeleteExistingPlot = false;
	  	if (pbJAI.getIntParameter("ShowPlot") == 1 )          optShowPlot           = true;	  	
	  	if (pbJAI.getIntParameter("DeleteExistingPlot") == 1) optDeleteExistingPlot = true;	  	

	  	int numBands  = pi.getData().getNumBands();
	  	String type        = IqmTools.getImgTyp(pi);
	    double typeGreyMax = IqmTools.getImgTypeGreyMax(pi);
	 
//	  	int pixelSize = pi.getColorModel().getPixelSize();
//		String type = IqmTools.getCurrImgTyp(pixelSize, numBands);
	  	String imgName  = (String) pi.getProperty("image_name");
	  	String fileName = (String) pi.getProperty("file_name");
 
	  	//initialize table for Dimension data
		DefaultTableModel model = new DefaultTableModel();
		JTable jTable  = new JTable(model);	
		//adding a lot of columns would be very slow due to active model listener
		model.removeTableModelListener(jTable);
		model.addColumn("FileName");
		model.addColumn("ImageName"); 
		model.addColumn("Band");
		model.addColumn("RegStart"); 
		model.addColumn("RegEnd"); 
		model.addColumn("Append"); 
		model.addColumn("Back"); 
		
		for(int b = 0; b < numBands; b++){ //mehrere Bands
			model.addRow(new Object[]{fileName, imgName, b, regStart, regEnd, optAppend, optBack});
		}	
	  	
		double[] dimX = new double[numBands]; 
		double[] dimY = new double[numBands]; 
		double[] dim  = new double[numBands]; 
		double[] p3X  = new double[numBands]; 
		double[] p3Y  = new double[numBands]; 
		double[] p3   = new double[numBands]; 
		double[] p4X  = new double[numBands]; 
		double[] p4Y  = new double[numBands]; 
		double[] p4   = new double[numBands]; 
		double[] p5X  = new double[numBands]; 
		double[] p5Y  = new double[numBands]; 
		double[] p5   = new double[numBands]; 
	  	double[][] regDataDimX  = new double[numK][numBands];
	  	double[][] regDataDimY  = new double[numK][numBands];
		double[][] regDataX = new double[numK][numBands];

		//values for Progress bar
		int prozX = 100;
		int prozY = 100;
		int offSetProzY = 0;
		if (optDx == 1) {
			prozY = 50; 
			offSetProzY = 50;
		}
		if (optDy == 1) {
			prozX = 50; 
		}			
		//-------------------------------------------------------------------------------------------------------------
		if (optAppend == 0){ //Project
			if (optDx == 1){		
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
				int[] pixel = new int[numBands];
				for (int x = 0; x < width; x++){
					int proz = (x+1)* prozX / width;
				   	Manager.setProgressBar(proz);				
				   	for (int b = 0; b < numBands; b++) (dataY.get(b)).add(0.0d);
					for (int y = 0; y < height; y++){
						raster.getPixel(x, y, pixel);						
						for (int b = 0; b < numBands; b++) dataY.get(b).set(x, ((Double)dataY.get(b).get(x)).doubleValue() + (double)pixel[b]);
					}			
				}
				for (int b = 0; b < numBands; b++){
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						//IqmTools.plotXY(dataYNew, true, "x", "y new");
						//System.out.println("IqmFracHiguchiOperator: dataY_New.size(): " + dataYNew.size());
						dataY.get(b).removeAllElements();
						//System.out.println("IqmFracHiguchiOperator: dataY_New.size(): " + dataYNew.size());
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}
						//IqmTools.plotXY(dataY.get(b), true, "x", "y without zeros");
						//System.out.println("IqmFracHiguchiOperator: dataY.get(b).size(): " + dataY.get(b).size());
					}
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhx:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimX[b] = -result[0];
					p3X[b]  = result[1];
					p4X[b]  = result[2];
					p5X[b]  = result[3];
					for (int i=0; i<numK; i++){
						regDataDimX[i][b] = L.get(i).doubleValue();
					}
				}
			} // optDx	
			if (optDy == 1){
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
				int[] pixel = new int[numBands];
				for (int y = 0; y < height; y++){
					int proz = (y+1)* prozY / width + offSetProzY;
					Manager.setProgressBar(proz);				
				   	for (int b = 0; b < numBands; b++) (dataY.get(b)).add(0.0d);
					for (int x = 0; x < width; x++){
						raster.getPixel(x, y, pixel);
						for (int b = 0; b < numBands; b++) dataY.get(b).set(y, ((Double)dataY.get(b).get(y)).doubleValue() + (double)pixel[b]);
					}			
				}
				for (int b = 0; b < numBands; b++){
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						//IqmTools.plotXY(dataYNew, true, "x", "y new");
						//System.out.println("IqmFracHiguchiOperator: dataY_New.size(): " + dataYNew.size());
						dataY.get(b).removeAllElements();
						//System.out.println("IqmFracHiguchiOperator: dataY_New.size(): " + dataYNew.size());
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}
						//IqmTools.plotXY(dataY.get(b), true, "x", "y without zeros");
						//System.out.println("IqmFracHiguchiOperator: dataY.get(b).size(): " + dataY.get(b).size());
					}
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhy:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimY[b] = -result[0];
					p3Y[b]  = result[1];
					p4Y[b]  = result[2];
					p5Y[b]  = result[3];
					for (int i=0; i<numK; i++){
						regDataDimY[i][b] = L.get(i).doubleValue();
					}
				}
			} // optDy	
		} //optAppend = 0  Project
		//-------------------------------------------------------------------------------------------------------------
		if (optAppend == 1){ //Separate
			if (optDx == 1){
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				int[] pixel = new int[numBands];
				Vector<Vector<Double>> dimXVec = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p3XVec  = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p4XVec  = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p5XVec  = new Vector<Vector<Double>>(); //for bands and separated results
				for (int b = 0; b < numBands; b++){
					dimXVec.add(new Vector<Double>()); //Initialize
					p3XVec.add(new Vector<Double>()); //Initialize
					p4XVec.add(new Vector<Double>()); //Initialize
					p5XVec.add(new Vector<Double>()); //Initialize
				}
				for (int y = 0; y < height; y++){
					int proz = (y+1)* prozX / height;
				   	Manager.setProgressBar(proz);				
					//Vector<Double> dataY = new Vector<Double>();
					Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
					for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
					for (int x = 0; x < width; x++){			
						raster.getPixel(x, y, pixel);
						for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);
					}
					for (int b = 0; b < numBands; b++) {
						if (optBack == 1){ //exclusive zeroes
							Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
							dataY.get(b).removeAllElements();
							for (int i = 0; i < dataYNew.size(); i++){
								(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
							}	
						}
						if (dataY.get(b).size() > numK*2){ //only data series which are large enough
							Higuchi hig = new Higuchi();
							//IqmTools.plotXY(dataY.get(b), true, "x", "y separate");			
							Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
							double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
							//BoardJ.appendTexln("IqmFracHiguchiOperator:  Dhx:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
							
							if (result[2] > 0.90) { //only higher r2  
								dimXVec.get(b).add(-result[0]);
								p3XVec.get(b).add(result[1]);
								p4XVec.get(b).add(result[2]);
								p5XVec.get(b).add(result[3]);
								for (int i=0; i<numK; i++){
									regDataDimX[i][b] = regDataDimX[i][b] + L.get(i).doubleValue();
								}
							}
						}
					}
				}
				//mean values
				for (int b = 0; b < numBands; b++) {
					for (int y = 0; y < dimXVec.get(b).size(); y++){
						dimX[b] = dimX[b] + dimXVec.get(b).get(y);
						p3X[b] = p3X[b] + p3XVec.get(b).get(y);
						p4X[b] = p4X[b] + p4XVec.get(b).get(y);
						p5X[b] = p5X[b] + p5XVec.get(b).get(y);				
					}
					//System.out.println("IqmFracHiguchiOperator: dimXVec.get(b).size() "+dimXVec.get(b).size());
					dimX[b] = dimX[b]/dimXVec.get(b).size();
					p3X[b] = p3X[b]/p3XVec.get(b).size();
					p4X[b] = p4X[b]/p4XVec.get(b).size();
					p5X[b] = p5X[b]/p5XVec.get(b).size();
					for (int i=0; i<numK; i++){
						regDataDimX[i][b] = regDataDimX[i][b]/dimXVec.get(b).size();
					}
					Board.appendTexln("IqmFracHiguchiOperator: Calulated number of series along x direction: "+ dimXVec.get(b).size());
				} //b bands
				

			} // optDx	
			if (optDy == 1){		
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				//int normY = width;
				int[] pixel = new int[numBands];
				Vector<Vector<Double>> dimYVec = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p3YVec  = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p4YVec  = new Vector<Vector<Double>>(); //for bands and separated results
				Vector<Vector<Double>> p5YVec  = new Vector<Vector<Double>>(); //for bands and separated results
				for (int b = 0; b < numBands; b++){
					dimYVec.add(new Vector<Double>()); //Initialize
					p3YVec.add(new Vector<Double>()); //Initialize
					p4YVec.add(new Vector<Double>()); //Initialize
					p5YVec.add(new Vector<Double>()); //Initialize
				}
				for (int x = 0; x < width; x++){
					int proz = (x+1)* prozY / width + offSetProzY;
					Manager.setProgressBar(proz);				
					//Vector<Double> dataY = new Vector<Double>();
					Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
					for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize						
					for (int y = 0; y < height; y++){
						raster.getPixel(x, y, pixel);
						for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);
					}
					for (int b = 0; b < numBands; b++) {
						if (optBack == 1){ //exclusive zeroes
							Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
							dataY.get(b).removeAllElements();
							for (int i = 0; i < dataYNew.size(); i++){
								(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
							}	
						}
						if (dataY.get(b).size() > numK*2){
							Higuchi hig = new Higuchi();
							Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
							double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
							//BoardJ.appendTexln("IqmFracHiguchiOperator:  Dhx:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
							dimYVec.get(b).add(-result[0]);
							p3YVec.get(b).add(result[1]);
							p4YVec.get(b).add(result[2]);
							p5YVec.get(b).add(result[3]);
							if (result[2] > 0.90) { //only higher r2  
								dimYVec.get(b).add(-result[0]);
								p3YVec.get(b).add(result[1]);
								p4YVec.get(b).add(result[2]);
								p5YVec.get(b).add(result[3]);
								for (int i=0; i<numK; i++){
									regDataDimY[i][b] = regDataDimY[i][b] + L.get(i).doubleValue();
								}
							}
						}
					}
				}	
				//mean
				for (int b = 0; b < numBands; b++) {
					for (int x = 0; x < dimYVec.get(b).size(); x++){
						dimY[b] = dimY[b] + dimYVec.get(b).get(x);
						p3Y[b] = p3Y[b] + p3YVec.get(b).get(x);
						p4Y[b] = p4Y[b] + p4YVec.get(b).get(x);
						p5Y[b] = p5Y[b] + p5YVec.get(b).get(x);				
					}
					dimY[b] = dimY[b]/dimYVec.get(b).size();
					p3Y[b] = p3Y[b]/p3YVec.get(b).size();
					p4Y[b] = p4Y[b]/p4YVec.get(b).size();
					p5Y[b] = p5Y[b]/p5YVec.get(b).size();
					for (int i=0; i<numK; i++){
						regDataDimY[i][b] = regDataDimY[i][b]/dimYVec.get(b).size();
					}
					Board.appendTexln("IqmFracHiguchiOperator: Calulated number of series along y direction: "+ dimYVec.get(b).size());
				}			
			} //optDy
		} //optAppend = 1  Separate
		//-------------------------------------------------------------------------------------------------------------
		if (optAppend == 2){ //Meander
			if (optDx == 1){		
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				//Vector<Double> dataY = new Vector<Double>(width*height);
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
				int[] pixel = new int[numBands];
				boolean even = false;
				for (int y = 0; y < height; y++){
					int proz = (y+1)* prozX / height;
				   	Manager.setProgressBar(proz);				
					if (y%2 == 0) even = true;
					if (y%2 != 0) even = false;
					//System.out.println("IqmFracHiguchiOperator: y: "+ y+ " even");
					if (even){
						for (int x = 0; x < width; x++){ //even
								raster.getPixel(x, y, pixel);
								for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]); 								
						}
					} else {
						for (int x = (width-1); x >= 0; x--){ //odd
							raster.getPixel(x, y, pixel);
							for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]); 						
					}
					}
				}
				for (int b = 0; b < numBands; b++) {
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						dataY.get(b).removeAllElements();
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}	
					}
					//IqmTools.plotXY(dataY.get(b), true, "x", "y new");
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhx:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimX[b] = -result[0];
					p3X[b]  = result[1];
					p4X[b]  = result[2];
					p5X[b]  = result[3];	
					for (int i=0; i<numK; i++){
						regDataDimX[i][b] = L.get(i).doubleValue();
					}
				} //b bands
			} // optDx	
			if (optDy == 1){
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				//Vector<Double> dataY = new Vector<Double>();
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
				int[] pixel = new int[numBands];
				boolean even = false;
				for (int x = 0; x < width; x++){
					int proz = (x+1)* prozY / width + offSetProzY;
					Manager.setProgressBar(proz);				
					if (x%2 == 0) even = true;
					if (x%2 != 0) even = false;
					//System.out.println("IamFracHiguchiOperator: x: "+ x+ " even");
					if (even){
						for (int y = 0; y < height; y++){ //even
							raster.getPixel(x, y, pixel);
							for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);		
						}						
					} else {
						for (int y = (height-1); y >= 0; y--){ //odd
							raster.getPixel(x, y, pixel);
							for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);		
						}						
					}	
				}
				for (int b = 0; b < numBands; b++) {
					//IqmTools.plotXY( dataY, true,  "x", "meander y");
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						dataY.get(b).removeAllElements();
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}	
					}
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhy:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimY[b] = -result[0];
					p3Y[b]  = result[1];
					p4Y[b]  = result[2];
					p5Y[b]  = result[3];	
					for (int i=0; i<numK; i++){
						regDataDimY[i][b] = L.get(i).doubleValue();
					}
				} //b bands
			} // optDy	
		} //optAppend = 2  Meander
		//-------------------------------------------------------------------------------------------------------------
		if (optAppend == 3){ //Contiguous
			if (optDx == 1){		
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				//Vector<Double> dataY = new Vector<Double>();
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize
				int[] pixel = new int[numBands];
				for (int y = 0; y < height; y++){
					int proz = (y+1)* prozX / height;
					Manager.setProgressBar(proz);				

					for (int x = 0; x < width; x++){
						raster.getPixel(x, y, pixel);
						for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);
					}			
				}
				for (int b = 0; b < numBands; b++) {
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						dataY.get(b).removeAllElements();
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}	
					}
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b, optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhx:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimX[b] = -result[0];
					p3X[b]  = result[1];
					p4X[b]  = result[2];
					p5X[b]  = result[3];	
					for (int i=0; i<numK; i++){
						regDataDimX[i][b] = L.get(i).doubleValue();
					}
				} //b bands
			} // optDx	
			if (optDy == 1){
				Raster raster = pi.getData();
				int width  = pi.getWidth();
				int height = pi.getHeight();
				//Vector<Double> dataY = new Vector<Double>();
				Vector<Vector<Double>> dataY = new Vector<Vector<Double>>(); //for bands
				for (int b = 0; b < numBands; b++) dataY.add(new Vector<Double>()); //Initialize			
				int[] pixel = new int[numBands];
				for (int x = 0; x < width; x++){
					int proz = (x+1)* prozY / width + offSetProzY;
					Manager.setProgressBar(proz);				

					for (int y = 0; y < height; y++){
						raster.getPixel(x, y, pixel);
						for (int b = 0; b < numBands; b++) dataY.get(b).add((double)pixel[b]);
					}			
				}	
				for (int b = 0; b < numBands; b++) {
					//IqmTools.plotXY( dataY, true,  "x", "contiguous y");
					if (optBack == 1){ //exclusive zeroes
						Vector<Double> dataYNew = this.removeZeroes(dataY.get(b));
						dataY.get(b).removeAllElements();
						for (int i = 0; i < dataYNew.size(); i++){
							(dataY.get(b)).add((Double)dataYNew.elementAt(i));						
						}	
					}
					Higuchi hig = new Higuchi();
					Vector<Double> L = hig.calcLengths(dataY.get(b), numK);
					double[] result = hig.calcDimension(L, 1, numK, imgName+"_Band"+b,  optShowPlot, optDeleteExistingPlot);
					Board.appendTexln("IqmFracHiguchiOperator  Dhy:" + (-result[0])+ " StdDev:" + result[1] + " r2:" + result[2] + " adj.r2:"+result[3]);
					dimY[b] = -result[0];
					p3Y[b]  = result[1];
					p4Y[b]  = result[2];
					p5Y[b]  = result[3];
					for (int i=0; i<numK; i++){
						regDataDimY[i][b] = L.get(i).doubleValue();
					}
				} //b bands
			} // optDy	
		} //optAppend = 3  Contiguous
		//-------------------------------------------------------------------------------------------------------------
		
		//Dh average or not
		if (optAppend == 0 || optAppend ==  1 || optAppend == 2 || optAppend == 3){ //eh alle
			for (int b = 0; b < numBands; b++) {
				if (optDx == 1 && optDy == 0){
					dim[b] = dimX[b];
					p3[b]  = p3X[b];
					p4[b]  = p4X[b];
					p5[b]  = p5X[b];
				}
				if (optDx == 0 && optDy == 1){
					dim[b] = dimY[b];
					p3[b]  = p3Y[b];
					p4[b]  = p4Y[b];
					p5[b]  = p5Y[b];
				}
				if (optDx == 1 && optDy == 1){
					dim[b] = (dimX[b] + dimY[b])/2;
					p3[b]  = (p3X[b] + p3Y[b])/2;
					p4[b]  = (p4X[b] + p4Y[b])/2;
					p5[b]  = (p5X[b] + p5Y[b])/2;
				}
			}
		}
		
		int numColumns = model.getColumnCount();
		model.addColumn("Dh_x");
		model.addColumn("Dh_y");
		model.addColumn("Dh");
		model.addColumn("StdDev_x");
		model.addColumn("StdDev_y");
		model.addColumn("StdDev");
		model.addColumn("r2_x");
		model.addColumn("r2_y");
		model.addColumn("r2");
		model.addColumn("adjustet r2_x");
		model.addColumn("adjustet r2_y");
		model.addColumn("adjustet r2");
		for (int n = 0; n < numK; n++) model.addColumn("DataX_"+(n+1));
		for (int n = 0; n < numK; n++) model.addColumn("DataDhx_"+(n+1));
		for (int n = 0; n < numK; n++) model.addColumn("DataDhy_"+(n+1));
	
		for(int b = 0; b < numBands; b++){ //several bands
			model.setValueAt(dimX[b], b, numColumns);
			model.setValueAt(dimY[b], b, numColumns+1);
			model.setValueAt(dim[b],  b, numColumns+2);
			model.setValueAt(p3X[b],  b, numColumns+3);	
			model.setValueAt(p3Y[b],  b, numColumns+4);	
			model.setValueAt(p3[b],   b, numColumns+5);	
			model.setValueAt(p4X[b],  b, numColumns+6);	
			model.setValueAt(p4Y[b],  b, numColumns+7);	
			model.setValueAt(p4[b],   b, numColumns+8);	
			model.setValueAt(p5X[b],  b, numColumns+9);	
			model.setValueAt(p5Y[b],  b, numColumns+10);	
			model.setValueAt(p5[b],   b, numColumns+11);	
			//set regression data
			for (int n = 0; n < numK; n++){	
				//model.setValueAt(lnBoxWidth[n][b],  b, numColumns+11+(n+1));
				model.setValueAt(n+1,  b, numColumns+11+(n+1));
			}
			for (int n = 0; n < numK; n++){	
				//model.setValueAt(lnTotals[n][b],  b, numColumns+11+number+(n+1));
				model.setValueAt(regDataDimX[n][b],  b, numColumns+11+ numK+(n+1));
			}
			for (int n = 0; n < numK; n++){	
				//model.setValueAt(lnTotals[n][b],  b, numColumns+11+number+(n+1));
				model.setValueAt(regDataDimY[n][b],  b, numColumns+11+ (2*numK)+(n+1));
			}
		}	
		model.addTableModelListener(jTable);
		model.fireTableStructureChanged(); //this is mandatory because it updates the table
		jTable.getColumnModel().getColumn(2).setPreferredWidth(30);  //Band					  
		jTable.getColumnModel().getColumn(3).setPreferredWidth(30);  //RegStart				  
		jTable.getColumnModel().getColumn(4).setPreferredWidth(30);  //RegEnd					  	  
		jTable.getColumnModel().getColumn(5).setPreferredWidth(30);  //Interp					  	  
        return jTable;
	    //return ob;   //Optional wird ein Bild ausgegeben
  }
}
